package com.shijie.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.shijie.component.AppUserService;
import com.shijie.component.redis.RedisClient;
import com.shijie.component.redis.RedisKey;
import com.shijie.core.AbstractService;
import com.shijie.domain.entity.*;
import com.shijie.domain.enums.EnumInterface;
import com.shijie.domain.enums.EnumInterface.EntityType;
import com.shijie.mapper.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;

import java.util.*;

/*
 *  @author: smart boy
 *  @date: 2018-08-06
 */
@Service
public class UserAttentionsService extends AbstractService<UserAttentions> {

    @Resource
    private UserAttentionsMapper userAttentionsMapper;

    @Resource
    private ProductsMapper productsMapper;

    @Resource
    private MagazinesMapper magazinesMapper;

    @Resource
    private UsersMapper usersMapper;

    @Resource
    private TalentsMapper talentsMapper;

    @Resource
    private AppUserService appUserService;

    @Autowired
    private RedisClient redisClient;


    /**
     * 客户需要的关注，喜欢，收藏内容
     *
     * @param userId
     * @param entityType 0资讯；1活动；2达人 ；3商品 ；4 内容（达人）',
     * @return
     */
    public PageInfo<?> attentions(Integer userId, EntityType entityType, int page, int pageSize) {

    	PageHelper.startPage(page, pageSize);
    	
        Example condition = new Example(UserAttentions.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("entityType", entityType.ordinal());

        criteria.andEqualTo("status", EnumInterface.Status.VALID.ordinal());

        List<UserAttentions> userAttentions = userAttentionsMapper.selectByCondition(condition);

        PageInfo pageInfo = new PageInfo<>(userAttentions);
        
        if (userAttentions.size() > 0) {
            List<Integer> ids = new ArrayList();
            for (UserAttentions userAttention : userAttentions) {
                ids.add(userAttention.getEntityId());
            }

            if (entityType.equals(EntityType.PRODUCT)) {

                Example conditionProduct = new Example(Products.class);
                Example.Criteria criteriaProduct = conditionProduct.createCriteria();
                criteriaProduct.andIn("id", ids);
                criteriaProduct.andEqualTo("status", EnumInterface.Status.VALID.ordinal());
                pageInfo.setList(productsMapper.selectByCondition(conditionProduct));
                return pageInfo;

            } else if (entityType.equals(EntityType.TALENT)) {

                Example conditionTalent = new Example(Talents.class);
                Example.Criteria criteriaTalent = conditionTalent.createCriteria();
                criteriaTalent.andIn("id", ids);
                conditionTalent.orderBy("id").desc();
                pageInfo.setList(talentsMapper.selectByCondition(conditionTalent));
                return pageInfo;

            } else {

                Example conditionOther = new Example(Magazines.class);
                Example.Criteria criteriaOther = conditionOther.createCriteria();
                criteriaOther.andIn("id", ids);
                criteriaOther.andEqualTo("status", EnumInterface.Status.VALID.ordinal());
                pageInfo.setList(magazinesMapper.selectByCondition(conditionOther));
                return pageInfo;

            }
        }

        return null;
    }


    /**
     * 单个资讯是否关注或点赞
     *
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public UserAttentions isAttentions(Integer userId, EntityType entityType, Integer entityId, Integer status) {
        return this.isAttentions(userId, entityType.ordinal(), entityId, status);
    }

    /**
     * 是否关注达人文章作者
     *
     * @param userId
     * @param talentId
     * @param status
     * @return
     */
    public Boolean isAttentionOwner(Integer userId, Integer talentId, Integer status) {

        Example condition = new Example(UserAttentions.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("entityType", EnumInterface.EntityType.TALENT_ARTICLE.ordinal())
                .andEqualTo("entityId", talentId);

        criteria.andEqualTo("status", EnumInterface.Status.VALID.ordinal());

        List<UserAttentions> attentions = userAttentionsMapper.selectByCondition(condition);

        return attentions.size() > 0 ? true : false;

    }

    /**
     * 是否关注达人
     *
     * @param userId
     * @param talentId
     * @param status
     * @return
     */
    public Boolean isAttentionTalentOwner(Integer userId, Integer talentId, Integer status) {

        Example condition = new Example(UserAttentions.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("entityType", EnumInterface.EntityType.TALENT.ordinal())
                .andEqualTo("entityId", talentId);
        criteria.andEqualTo("status", EnumInterface.Status.VALID.ordinal());
        List<UserAttentions> attentions = userAttentionsMapper.selectByCondition(condition);
        return attentions.size() > 0 ? true : false;

    }

    /**
     * 获取到对应的关注内容
     *
     * @param userId
     * @param entityType
     * @param entityId
     * @param status
     * @return
     */
    public UserAttentions isAttentions(Integer userId, Integer entityType, Integer entityId, Integer status) {

        Example condition = new Example(UserAttentions.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("entityType", entityType).
                andEqualTo("entityId", entityId);
        if (status != null) {
            criteria.andEqualTo("status", EnumInterface.Status.VALID.ordinal());
        }
        List<UserAttentions> attentions = userAttentionsMapper.selectByCondition(condition);
        return attentions.size() > 0 ? attentions.get(0) : null;
    }

    /**
     * 资讯类的关注
     * 资讯内容是否关注
     * 达人文章时，判断文章作者是否关注
     *
     * @param userId
     * @param Magazines
     * @return
     */
    public void attentions(Integer userId, List<Magazines> Magazines) {

        for (Magazines magazine : Magazines) {
            // 是否关注喜欢该内容
            UserAttentions attentions = this.isAttentions(userId, magazine.getType(), magazine.getId(),
                    EnumInterface.Status.VALID.ordinal());
            magazine.setIsAttentions(attentions == null ? Boolean.FALSE : Boolean.TRUE);

            // 达人文章时
            if (EnumInterface.EntityType.TALENT_ARTICLE.ordinal() == magazine.getType()) {

                // 判断是否关注达人
                magazine.setIsAttentionOwner(this.isAttentionOwner(appUserService.getCurrentUser().getId(),
                        magazine.getOwnerId(), EnumInterface.Status.VALID.ordinal()));
            }
        }
    }

    /**
     * 批量是否关注或点赞
     *
     * @param userId
     * @param entityTypes
     * @param entityIds
     * @return
     */
    public List<UserAttentions> isAttentionses(Long userId, List<Integer> entityIds, List<Integer> entityTypes) {
        Example condition = new Example(UserAttentions.class);
        condition.createCriteria().andEqualTo("userId", userId).andIn("entityType", entityTypes).andIn("entityId", entityIds)
                .andEqualTo("status", EnumInterface.Status.VALID.ordinal());
        return userAttentionsMapper.selectByCondition(condition);
    }


    @Transactional
    public Integer like(Integer id, EntityType entityType) {
        // 默认是喜欢
        boolean isLike = true;
        UserAttentions userAttentions = this.isAttentions(appUserService.getCurrentUser().getId(), entityType, id, null);
        if (userAttentions == null) {
            userAttentions = new UserAttentions();
            userAttentions.setUserId(appUserService.getCurrentUser().getId());
            userAttentions.setUserName(appUserService.getUserName());
            userAttentions.setEntityId(id);
            userAttentions.setEntityType(entityType.ordinal());
            userAttentions.setCreateBy(appUserService.getUserName());
            userAttentions.setStatus(EnumInterface.Status.VALID.ordinal());
            userAttentions.setCreateTime(new Date());
            this.save(userAttentions);
        } else {
            if (userAttentions.getStatus().equals(EnumInterface.Status.VALID.ordinal())) {
                isLike = false;
            }
            userAttentions.setStatus((userAttentions.getStatus().equals(EnumInterface.Status.VALID.ordinal())) ? EnumInterface.Status.INVALID.ordinal() : EnumInterface.Status.VALID.ordinal());
            userAttentions.setUpdateBy(appUserService.getUserName());
            userAttentions.setUpdateTime(new Date());
            this.updateById(userAttentions);
        }
        return updateNumForMag(id, entityType, isLike, appUserService.getCurrentUser().getId());
    }

    /**
     * 更新喜欢对象的总和
     *
     * @param id
     * @param entityType
     * @param isLike     true 喜欢，false 取消
     */
    private Integer updateNumForMag(Integer id, EntityType entityType, boolean isLike, Integer userId) {
        Integer newNum = 0;
        if (EntityType.PRODUCT.equals(entityType)) {
            Products products = productsMapper.selectByPrimaryKey(id);
            Products update = new Products();
            update.setId(products.getId());
            if (isLike == true) {
                newNum = products.getFavorites() + 1;
            } else {
                newNum = products.getFavorites() - 1;
            }
            update.setFavorites(newNum);
            productsMapper.updateByPrimaryKeySelective(update);

        } else if (EntityType.TALENT.equals(entityType)) {
            Talents talents = talentsMapper.selectByPrimaryKey(id);

            Talents update = new Talents();
            update.setId(talents.getId());
            if (isLike == true) {
                newNum = talents.getFans() + 1;
            } else {
                newNum = talents.getFans() - 1;
            }
            update.setFans(newNum);
            talentsMapper.updateByPrimaryKeySelective(update);

        } else {
            Magazines magazines = magazinesMapper.selectByPrimaryKey(id);
            Magazines update = new Magazines();
            update.setId(magazines.getId());
            if (isLike == true) {
                newNum = magazines.getFavorites() + 1;
            } else {
                newNum = magazines.getFavorites() - 1;
            }
            update.setFavorites(newNum);
            magazinesMapper.updateByPrimaryKeySelective(update);

            // 如果是达人的文章点赞关注，需要更新达人用户的被点赞数
            if (EntityType.TALENT_ARTICLE.equals(entityType)) {
                Talents talents = talentsMapper.selectByPrimaryKey(magazines.getOwnerId());

                Talents updateU = new Talents();
                updateU.setId(talents.getId());

                if (isLike == true) {
                    newNum = talents.getUpVotes() + 1;
                } else {
                    newNum = talents.getUpVotes() - 1;
                }
                updateU.setUpVotes(newNum);
                talentsMapper.updateByPrimaryKeySelective(updateU);
            }
        }

        // 更新客户自己的信息 关注数 喜欢数(自己喜欢的产品数)
        Users customer = usersMapper.detailForUser(userId);

        Talents talents = new Talents();
        talents.setUserId(customer.getId());
        talents = talentsMapper.selectOne(talents);

        Talents updateUser = new Talents();
        updateUser.setId(talents.getId());

        if (isLike == true) {
            if (EntityType.PRODUCT.equals(entityType)) {
                // 喜欢数(自己喜欢的产品数)
                updateUser.setFavorites(customer.getFavorites() + 1);
            } else {
                // 关注数
                updateUser.setInterests(customer.getInterests() + 1);
            }
        } else {
            if (EntityType.PRODUCT.equals(entityType)) {
                // 喜欢数(自己喜欢的产品数)
                updateUser.setFavorites(customer.getFavorites() - 1);
            } else {
                // 关注数
                updateUser.setInterests(customer.getInterests() - 1);
            }
        }

        talentsMapper.updateByPrimaryKeySelective(updateUser);
        return newNum;
    }

    /**
     * 返回客户点击率最高分类的藏品 ,暂定为 6个
     *
     * @param isLogin
     * @return
     */
    public List<Products> userLikeProducts(Boolean isLogin) {
        Integer num = 6;
        List<Products> productList = new ArrayList<>();

        PageHelper.startPage(1, 10);

        Example condition = new Example(Products.class);
        Example.Criteria criteria = condition.createCriteria();

        if (isLogin) {
            // 取出用户浏览最多的两个分类
            Set<ZSetOperations.TypedTuple<Object>> reverseRangeByScoreWithScores =
                    redisClient.getLimitTopSet(String.format(RedisKey.APP_USER_CATEGORY, appUserService.getCurrentUser().getId()), 2);

            List<Integer> categoryIds = new ArrayList<>();
            if (reverseRangeByScoreWithScores != null) {
                Iterator<ZSetOperations.TypedTuple<Object>> iterator = reverseRangeByScoreWithScores.iterator();
                while (iterator.hasNext()) {
                    ZSetOperations.TypedTuple<Object> next = iterator.next();
                    categoryIds.add(Integer.parseInt(next.getValue().toString()));
                }
            }

            if (categoryIds.size() > 0) {
                criteria.andIn("categoryId", categoryIds);
            }

        } else {
            // 取PV最高的6个商品 ，作为推荐
            Set<ZSetOperations.TypedTuple<Object>> reverseRangeByScoreWithScores =
                    redisClient.getLimitTopSet(RedisKey.APP_PRODUCT_PV, 15);

            List<Integer> ids = new ArrayList<>();

            if (reverseRangeByScoreWithScores != null) {
                Iterator<ZSetOperations.TypedTuple<Object>> iterator = reverseRangeByScoreWithScores.iterator();

                while (iterator.hasNext()) {
                    ZSetOperations.TypedTuple<Object> next = iterator.next();
                    productList.add(productsMapper.selectByPrimaryKey(next.getValue()));
                }
            }

            if (ids.size() > 0) {
                criteria.andIn("id", ids);
            }
        }

        criteria.andEqualTo("status", EnumInterface.Status.VALID.ordinal());

        condition.orderBy("id").desc();
        List<Products> list = productsMapper.selectByCondition(condition);

        productList = list.subList(0, num > list.size() ? list.size() : num);

        return productList;
    }
}
